# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: xguo
import datetime
import pytz

from coin.exchange.base.kr_rest.public_client_base import PublicClientBase
from coin.exchange.okex_v3.kr_rest.native_public_client import OkexNativePublicClient
from coin.exchange.okex.kr_rest.product import (
    get_active_symbol_list,
    OkexProduct,
)

import dateutil.parser

from coin.proto.coin_market_query_pb2 import (
    ProductTicker,
    ExchangeTicker,
    ProductKlineElement,
    ProductKline,
)


class OkexFeedParser(object):
  @staticmethod
  def parse_native_ticker(ticker, product):
    assert ticker['instrument_id'] == product.native_symbol_v3
    timestamp = dateutil.parser.parse(ticker['timestamp']).timestamp() * 1e+9
    timestamp = int(timestamp)
    return ProductTicker(
        high=float(ticker['high_24h']),
        low=float(ticker['low_24h']),
        last=float(ticker['last']),
        ask=float(ticker['ask']),
        bid=float(ticker['bid']),
        volume_24hr=float(ticker['base_volume_24h']),  # Last rolling 24 hours.
        exchange_timestamp=timestamp,
        native_symbol=product.native_symbol,
        symbol=product.symbol)

  @staticmethod
  def parse_native_kline(update_msg, product, kline_period):
    klines = update_msg
    kline_group = []
    for kline in klines:
      kline_dt = datetime.datetime.strptime(kline[0], '%Y-%m-%dT%H:%M:%S.%fZ')
      kline_ts = kline_dt.replace(tzinfo=pytz.UTC).timestamp() * 1e+9
      product_kline = ProductKlineElement(
          kline_timestamp=int(kline_ts),
          open=float(kline[1]),
          high=float(kline[2]),
          low=float(kline[3]),
          close=float(kline[4]),
          volume=float(kline[5]),
      )
      kline_group.append(product_kline)
    return ProductKline(
        symbol=product.symbol,
        native_symbol=product.native_symbol,
        exchange='Okex',
        market_type='Spot',
        kline_period=str(kline_period),
        klines=kline_group,
    )

  @staticmethod
  def parse_exchange_ticker(exchange_ticker):
    product_ticker_list = []
    for ticker in exchange_ticker:
      product = OkexProduct.FromStrNativeProductNothrow(ticker['instrument_id'])
      if product is None:
        continue
      product_ticker = OkexFeedParser.parse_native_ticker(ticker, product)
      product_ticker_list.append(product_ticker)

    return ExchangeTicker(exchange='Okex', each_ticker=product_ticker_list)


class OkexPublicClient(PublicClientBase):
  ProductType = OkexProduct

  def __init__(self, timeout=10):
    self.npubc = OkexNativePublicClient(timeout=timeout)

  def query_ticker_impl(self, product):
    symbol = product.native_symbol
    update = self.npubc.get_ticker(symbol)
    update.msg = OkexFeedParser.parse_native_ticker(update.msg, product)
    return update

  def query_exchange_ticker_impl(self):
    update = self.npubc.get_exchange_ticker()
    update.msg = OkexFeedParser.parse_exchange_ticker(update.msg)
    return update

  def query_history_kline_impl(self, product, kline_period, start_time, end_time):
    native_symbol = product.native_symbol
    update = self.npubc.get_history_kline(native_symbol, kline_period, start_time, end_time)
    update.msg = OkexFeedParser.parse_native_kline(update.msg, product, kline_period)
    return update

  def query_level_book_impl(self, product):
    raise NotImplementedError()
